<?php

namespace app\api\service;

use app\admin\model\AuthGroupAccess;
use app\admin\model\AuthRule;
use app\api\model\AdminModel;
use app\api\model\AuthGroupAccessModel;
use app\api\model\MenuModel;
use think\Db;
use think\Request;

class MenuService extends Api
{
    protected static $instance;

    public function __construct(Request $request = null)
    {
        parent::__construct($request);
    }

    public static function getInstance()
    {
        if (is_null(self::$instance))
        {
            self::$instance = new static();
        }
        return self::$instance;
    }

    /**
     * 添加菜单
     */
    public function addMenu($params)
    {
        $Validate = new \think\Validate([
            'pid' => 'require',//父级
            'title' => 'require',//标题
            'name' => 'require',//URL
            'condition' => 'require',//标识
            'weigh' => 'require',//权重
            'type' => 'require',//是menu为菜单,file为权限节点
            'status' => 'require',//菜单状态：0 隐藏  1 显示
        ]);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }

        self::menuRule($params);

        $saveData = [
            'type' => $params['type'],//'menu为菜单,file为权限节点',
            'pid' => $params['pid'],
            'name' => $params['name'],
            'title' => $params['title'],
            'icon' => $this->request->param('icon', '#000000'),//'图标',
            'condition' => $params['condition'],
            'remark' => $this->request->param('remark', ''),//'备注',
            'ismenu' => $params['type'] == 'menu' ? 1 : 0,
            'createtime' => time(),
            'weigh' => $params['weigh'],
            'status' => $params['status'],
        ];
        $result = MenuModel::getInstance()->add($saveData);
        return $result;
    }

    /**
     * 编辑菜单
     */
    public function editMenu($params)
    {
        $type = $this->request->param('type', 'menu');
        $checkData = [
            'id' => 'require',//菜单ID
            'pid' => 'require',//父级
            'title' => 'require',//标题
            'condition' => 'require',//标识
            'weigh' => 'require',//权重
            'type' => 'require',//是menu为菜单,file为权限节点
            'status' => 'require',//菜单状态：0 隐藏  1 显示
        ];
        if ($type == 'menu')
        {
            $checkData['name'] = 'require';
        }
        $Validate = new \think\Validate($checkData);
        if (!$Validate->check($params))
        {
            $this->error($Validate->getError());
        }

        self::menuRule($params);

        $saveData = [
            'type' => $params['type'],//'menu为菜单,file为权限节点',
            'pid' => $params['pid'],
            'name' => $params['name'],
            'title' => $params['title'],
            'icon' => $this->request->param('icon', '#000000'),//'图标',
            'condition' => $params['condition'],
            'remark' => $this->request->param('remark', ''),//'备注',
            'ismenu' => $params['type'] == 'menu' ? 1 : 0,
            'updatetime' => time(),
            'weigh' => $params['weigh'],
            'status' => $params['status'],
        ];
        return MenuModel::getInstance()->edit([
            'id' => ['eq', $params['id']]
        ], $saveData);
    }

    /**
     * 菜单信息规则限制
     */
    public function menuRule($params)
    {
        $menuWhere['name'] = ['eq', $params['name']];
        if (isset($params['id']))
        {
            $menuWhere['id'] = ['neq', $params['id']];
            $buttonWhere['id'] = ['neq', $params['id']];
            $menuIds = self::getMenuIds($params['id']);
            if (in_array($params['pid'], explode(',', $menuIds)) && !empty($params['id']))
            {
                $this->error('菜单级别不允许设置本身和下级为父级');
            }
        }
        $authMenu = MenuModel::getInstance()->find($menuWhere);
        if ($authMenu)
        {
            $this->error('路由规则重复');
        }
        $buttonWhere['condition'] = ['eq', $params['condition']];
        $menu = MenuModel::getInstance()->find($buttonWhere);
        if ($menu && $params['type'] == 'file')
        {
            $this->error('标识规则重复');
        }

        return true;
    }

    /**
     * 获取指定菜单及其下级ID
     */
    public function getMenuIds($mid)
    {
        $ids = $mid;
        $child = MenuModel::getInstance()->select([
            'pid' => ['eq', $mid]
        ]);
        if ($child)
        {
            $ids .= ','.implode(',', array_column($child, 'id'));
            foreach ($child as $k => $v)
            {
                $ids .= ','.self::getMenuIds($v['id']);
            }
        }
        return $ids;
    }

    /**
     * 获取指定菜单信息
     */
    public function getMenuInfo($params)
    {
        $mid = $this->request->param('mid', 0);
        $mInfo = MenuModel::getInstance()->select(['id' => $mid]);
        return $mInfo ? $mInfo[0] : [];
    }

    /**
     * 设置菜单启用状态
     */
    public function setMenuStatus($params)
    {
        $mid = $this->request->param('mid', 0);
        $isEnable = $this->request->param('isEnable', 1);
        return MenuModel::getInstance()->edit([
            'id' => ['eq', $mid]
        ], [
            'isenable' => $isEnable
        ]);
    }

    /**
     * 获取菜单列表
     */
    public function getMeunList($params)
    {
        $where = [];

        if (isset($params['title']))
        {
            $where['title'] = ['LIKE', '%'.$params['title'].'%'];
        }
        if (isset($params['isEnable']))
        {
            $where['isenable'] = ['eq', $params['isEnable']];
        }
        if (isset($params['status']))
        {
            $where['status'] = ['eq', $params['status']];
        }

        $list = MenuModel::getInstance()->select($where);
        $menuList = !empty($where) ? $list : self::getMenuTree($list);
        return $menuList;
    }

    /**
     * 组建树级结构
     */
    public function getMenuTree($data, $pid = 0, $level = 0)
    {
        $menuList = [];
        foreach ($data as $k => $v)
        {
            if ($v['pid'] == $pid)
            {
                $v['level'] = $level;
                unset($data[$k]);
                $v['child'] = self::getMenuTree($data, $v['id'], $level + 1);
                if (empty($v['child']))
                {
                    unset($v['child']);
                }
                $menuList[] = $v;
            }
        }
        return $menuList;
    }

    /**
     * 获取父级
     */
    public function getParentIds($data, $id, $isArr = false)
    {
        $result = [];
        foreach ($data as $k => $v)
        {
            if ($isArr)
            {
                if (in_array($v['id'], $id))
                {
                    $result[] = $v['pid'];
                    $result = array_merge($this->getParentIds($data, $v['pid']), $result);
                }
            }else{
                if ($v['id'] == $id)
                {
                    $result[] = $v['pid'];
                    $result = array_merge($this->getParentIds($data, $v['pid']), $result);
                }
            }

        }
        return empty($result) && $id == 1 ? [1] : $result;
    }

    /**
     * 获取下级
     */
    public function getChildIds($data, $ids)
    {
        foreach ($data as $k => $v)
        {
            if (in_array($v['pid'], $ids))
            {
                $ids[] = $v['id'];
                /*unset($data[$k]);
                $childIds = array_merge(self::getChildIds($data, $ids), $ids);
                if (!empty($childIds))
                {
                    $ids = array_merge($childIds, $ids);
                }*/
            }
        }
        return $ids;
    }

    /**
     * 根据用户组获取可用菜单
     */
    public function getUserRules($field = '*')
    {
        $groupIds = AuthGroupAccessModel::getInstance()->column($this->uid);
        $menu = self::getUserMenu($field, $groupIds, true);
        return self::getMenuTree($menu);
    }

    /**
     * 获取用户可用菜单
     */
    public function getUserMenu($field = '*', $groupId = '', $isPid = false)
    {
        $groupId = empty($groupId) ? 1 : $groupId;
        $rules = AdminModel::getInstance()->columnGroup($groupId);
        $rules = implode(',', $rules);
        if ($isPid)
        {
            $pIds = Db::name('auth_rule')->field('id,pid')->select();
            $pid = [];
            foreach (explode(',', $rules) as $k => $v)
            {
                $pid[] = $v;
                $pid = array_merge(MenuService::getInstance()->getParentIds($pIds, $v), $pid);
            }
            $rules .= ','.implode(',', $pid);
        }
        if (strpos($rules, '*') !== false)
        {
            $rules = MenuModel::getInstance()->column([], 'id');
            $rules = implode(',', $rules);
        }
        $menu = MenuModel::getInstance()->select([
            'id' => ['in', $rules],
            'isenable' => ['eq', 1]
        ], $field);
        return $menu;
    }

    /**
     * 获取系统账号可查看菜单  需要依据当前账号 角色 权限 读取可用菜单
     */
    public function getMenu()
    {
        $rules = self::getUserRules();

        foreach ($rules as $k => $v)
        {
            if (empty($v['child']))
            {
                $level1[$k] = [
                    'path' => $v['name'],
                    'component' => 'Layout',
                    'redirect' => $v['name'],
                    'hidden' => empty($v['status']) ? true : false,
                    'children' => [
                        [
                            'path' => $v['name'],
                            'name' => $v['condition'],
                            'component' => $v['condition'],
                            'hidden' => empty($v['status']) ? true : false,
                            'meta' =>
                                [
                                    'title' => $v['title'],
                                    'icon' => $v['icon'],
                                ]
                        ]
                    ]
                ];
            }else{
                $level1[$k] = [
                    'path' => $v['name'],
                    'component' => 'Layout',
                    'redirect' => $v['child'][0]['name'],
                    'hidden' => empty($v['status']) ? true : false,
                    'meta' => [
                        'title' => $v['title'],
                        'icon' => $v['icon'],
                        'alert' => 0//$v['weigh']
                    ],
                ];
                foreach ($v['child'] as $kk => $vv)
                {
                    $level1[$k]['children'][$kk] = [
                        'path' => $vv['name'],
                        'name' => $vv['condition'],
                        'component' => $vv['condition'],
                        'hidden' => empty($vv['status']) ? true : false,
                        'meta' => [
                            'title' => $vv['title'],
                            'icon' => $vv['icon'],
                            'alert' => 0//$vv['weigh']
                        ]
                    ];
                    if (!empty($vv['child']))
                    {
                        foreach ($vv['child'] as $kkk => $vvv)
                        {
                            $level1[$k]['children'][$kk]['children'][$kkk] = [
                                'path' => $vvv['name'],
                                'name' => $vvv['condition'],
                                'component' => $vvv['condition'],
                                'hidden' => true,
                                'meta' => [
                                    'title' => $vvv['title'],
                                    'icon' => $vvv['icon'],
                                    'alert' => 0//$vvv['weigh']
                                ]
                            ];
                        }
                    }
                }
            }
        }

        return [
            'router' => $level1
        ];
    }
}